#include <iostream>
#include <memory>
#include <string>
// 建造者模式
// 1.先创建产品的抽象类
class Computer
{
public:
    // 构建零部件的方法
    void setBoard(const std::string &board)
    {
        _board = board;
    }
    void setDisply(const std::string &display)
    {
        _display = display;
    }
    virtual void setOs() = 0;
    std::string toString()
    {
        std::string computer = "Computer:{\n";
        computer += "\tboard=" + _board + ",\n";
        computer += "\tdisplay=" + _display + ",\n";
        computer += "\tOs=" + _os + ",\n";
        computer += "}\n";
        return computer;
    }

protected: // 如果是私有的零部件，
    // 这是我们构造电脑所需要的零部件。
    std::string _board;   // 主板
    std::string _display; // 显示屏
    std::string _os;      // 操作系统
};

// 2.对产品抽象接口的具体实现
class MacBook : public Computer
{
public:
    // 构建抽象零部件的方法
    void setOs() override
    {
        _os = "Mac os x12";
    }
};

// 3.完成各个零部件的生产过程
class Builder
{
public:
    virtual void builBoard(const std::string &board) = 0;
    virtual void builDisplay(const std::string &display) = 0;
    virtual void builOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 4.实现抽象接⼝，构建各个部件
class MacBookBuild : public Builder
{
public:
    MacBookBuild() : _computer(new MacBook()) {}
    void builBoard(const std::string &board)
    {
        _computer->setBoard(board);
    }
    void builDisplay(const std::string &display)
    {
        _computer->setDisply(display);
    }
    void builOs()
    {
        _computer->setOs();
    }
    std::shared_ptr<Computer> build()
    {
        return _computer;
    }
    std::shared_ptr<Computer> _computer;
};

// 指挥者
class Director
{
public:
    Director(Builder *builder) : _builder(builder) {}
    void construct(const std::string &board, const std::string &display)
    {
        _builder->builBoard(board);
        _builder->builDisplay(display);
        _builder->builOs();
    }

private:
    std::shared_ptr<Builder> _builder;
};

int main()
{
    Builder *builder = new MacBookBuild();                     // 苹果系统的建造者构造
    std::unique_ptr<Director> director(new Director(builder)); // 指挥者准备好了
    director->construct("华硕主板", "三星显示器");             // 组装好了
    std::shared_ptr<Computer> computer = builder->build();     //
    std::cout << computer->toString();
    return 0;
}